import 'package:flutter/material.dart';
import 'package:my_flutter_core/extensions/string_extension.dart';

/// Builds a list of [TextSpan] with all [keywords] highlighted using [highlightStyle].
List<TextSpan> buildTextSpansWithKeywords(
  String content,
  List<String>? keywords, {
  TextStyle highlightStyle = const TextStyle(
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
}) {
  var children = <TextSpan>[];

  if (keywords != null && keywords.isNotEmpty) {
    for (final keyword in keywords) {
      if (keyword == keywords.first) {
        children = buildTextSpansWithKeyword(
          content,
          keyword,
          highlightStyle: highlightStyle,
        );
      } else {
        for (var i = 0; i < children.length; i++) {
          final textSpan = children[i];
          if (textSpan.style == null &&
              textSpan.text.isNotNullOrEmpty &&
              textSpan.text!.contains(keyword)) {
            children.insertAll(
              i,
              buildTextSpansWithKeyword(
                children[i].text,
                keyword,
                highlightStyle: highlightStyle,
              ),
            );
            children.remove(textSpan);
          }
        }
      }
    }
  } else {
    children = [TextSpan(text: content)];
  }

  return children;
}

/// Builds [TextSpan] list highlighting a single [keyword] in [content].
List<TextSpan> buildTextSpansWithKeyword(
  String? content,
  String keyword, {
  TextStyle highlightStyle = const TextStyle(
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
}) {
  final children = <TextSpan>[];
  final indexes = content.allIndexesOf(keyword);

  if (indexes.isNotEmpty) {
    for (var i = 0; i < indexes.length; i++) {
      final index = indexes[i];
      if (i == 0) {
        children.add(TextSpan(text: content!.substring(0, index)));
      } else {
        children.add(
          TextSpan(text: content!.substring(indexes[i - 1] + 1, index)),
        );
      }

      children.add(TextSpan(text: keyword, style: highlightStyle));

      if (i == indexes.length - 1 && index < content.length - 1) {
        children.add(TextSpan(text: content.substring(index + keyword.length)));
      }
    }
  } else {
    children.add(TextSpan(text: content));
  }

  return children;
}

/// Executes a [callback] after the current frame is rendered.
void addPostFrameCallback(VoidCallback callback) {
  WidgetsBinding.instance.addPostFrameCallback((_) {
    callback();
  });
}
